<?php
/**
 * ===============================================
 * 版权所有 2019-2050 青岛铁锤科技有限公司，并保留所有权利。
 * 网站地址: http://www.huaxianling.com
 * ===============================================
 * Author: Alex
 * Created Time: 2019/7/4 10:53
 * Modified Time: 2019/7/4 10:53
 * Version: 2.0
 */

namespace App\Lib;

use AlibabaCloud\Client\AlibabaCloud;
use App\Exceptions\AllValidatorException;
use App\Models\Picture;
use App\Models\User;
use App\Models\Video;
use Flower\Core\Repository\Exceptions\ValidatorException;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\MessageBag;

//阿里云
use OSS\OssClient;
use OSS\Core\OssException;

/**
 * 公共类库
 * Class Utilities
 * @package App\Lib
 */
class Utilities
{
    private $a;


    /*
     * Raghu 19-7-4
     * 服务层判断请求是否包含某值
     * $requestData:Array
     * $rule:Array
     */
    public static function checkRequestDataKeyExist($requestData = [], $data_rule = [])
    {
        foreach ($data_rule as $key => $value) {

            if (!array_key_exists($key, $requestData)) {
                throw new AllValidatorException(['msg' => $value]);
            }

        }

    }

    /**
     * 测试类获取测试账号token
     * @return mixed
     */
    public static function testGetToken()
    {
        $user = User::find(65);

        return $user->token;
    }

    /**
     * 生成随机汉字
     * @param $num
     * @return string
     */
    public static function getChar($num)  // $num为生成汉字的数量
    {
        $b = '';
        for ($i = 0; $i < $num; $i++) {
            // 使用chr()函数拼接双字节汉字，前一个chr()为高位字节，后一个为低位字节
            $a = chr(mt_rand(0xB0, 0xD0)) . chr(mt_rand(0xA1, 0xF0));
            // 转码
            $b .= iconv('GB2312', 'UTF-8', $a);
        }
        return $b;
    }

    /**
     * 格式化时间 7.29 周二 10：32：10
     * @param $date
     * @return string
     *
     */
    public static function wxDateFormat($date)
    {
        $weekDay = ['周日', '周一', '周一', '周三', '周四', '周五', '周六'];
        $data = strtotime($date) ? strtotime($date) : $date;
        $dateFormat = date('n.j w H:i:s', $data);
        $dateFormat = explode(' ', $dateFormat);
        $dateFormat[1] = $weekDay[$dateFormat[1]];
        return implode(' ', $dateFormat);
    }

    /**
     * array_column的升级版
     * @param $array
     * @param $columnKey
     * @param null $indexKey
     * @return array
     */
    public static function arrayColumnGroup($array, $columnKey, $indexKey = null)
    {
        $result = array();
        foreach ($array as $subArray) {
            if (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
                $result[] = is_object($subArray) ? $subArray->$columnKey : $subArray[$columnKey];
            } elseif (array_key_exists($indexKey, $subArray)) {
                if (is_null($columnKey)) {
                    $index = is_object($subArray) ? $subArray->$indexKey : $subArray[$indexKey];
                    $result[$index][] = $subArray;
                } elseif (array_key_exists($columnKey, $subArray)) {
                    $index = is_object($subArray) ? $subArray->$indexKey : $subArray[$indexKey];
                    $result[$index][] = is_object($subArray) ? $subArray->$columnKey : $subArray[$columnKey];
                }
            }
        }
        return $result;
    }

    /**
     * 多维数组将纬成一纬数组
     * @param $arr
     * @return array|bool
     * Modified Time : 2019-07-15 18:07
     */
    public static function reduceArray($arr)
    {
        $res = [];
        if (is_array($arr) && !empty($arr)) {
            array_walk_recursive($arr, function ($v) use (&$res) {
                $res[] = $v;
            });
        }
        return $res;
    }


    /**
     * 处理中间数据 -> 资源数据的处理
     * @param $resource
     * @param $field
     * @return array
     */
    public static function dataFormat($resource, $field)
    {
        $List = array_filter($resource, function ($v) use ($field) {
            return !empty($v[$field]);
        });
        return empty($List) ? [] : Utilities::arrayColumnGroup($List, $field);
    }


    /*
     * Raghu 19-7-8
     * 发送手机短信验证码
     * $phone :手机号码
     * $scene : 使用场景
     */
    public static function sendSmsCode($phone, $scene)
    {
        $scene_arr = config('constant.sms_scene');

        if (ENV('APP_ENV') == 'production') {
            $code = rand(100000, 999999);
            $key = 'code:' . $phone . ':' . $scene_arr[$scene];
            Redis::setex($key, 300, $code);

            $access_key_id = config('constant.aliSms.access_key_id');
            $access_key_secret = config('constant.aliSms.access_key_secret');


            AlibabaCloud::accessKeyClient($access_key_id, $access_key_secret)
                ->regionId('cn-beijing')// replace regionId as you need
                ->asGlobalClient();
            try {
                $result = AlibabaCloud::rpcRequest()
                    ->product('Dysmsapi')
                    // ->scheme('https') // https | http
                    ->version('2017-05-25')
                    ->action('SendSms')
                    ->method('POST')
                    ->options([
                        'query' => [
                            'PhoneNumbers' => $phone,
                            'SignName' => '花县令',
                            'TemplateCode' => 'SMS_157284495',
                            'TemplateParam' => json_encode(['code' => $code]),
                        ],
                    ])
                    ->request();
//                print_r($result->toArray());
                return ['status' => 1, 'msg' => ''];
            } catch (ClientException $e) {
                // echo $e->getErrorMessage() . PHP_EOL;
                return ['status' => 0, 'msg' => $e->getErrorMessage()];
            } catch (ServerException $e) {
                // echo $e->getErrorMessage() . PHP_EOL;
                return ['status' => 0, 'msg' => $e->getErrorMessage()];
            }
        } else {
            $code = 111111;
            $key = 'code:' . $phone . ':' . $scene_arr[$scene];
            Redis::setex($key, 300, $code);
            try {
                return ['status' => 1, 'msg' => ''];
            } catch (ClientException $e) {
                // echo $e->getErrorMessage() . PHP_EOL;
                return ['status' => 0, 'msg' => $e->getErrorMessage()];
            } catch (ServerException $e) {
                // echo $e->getErrorMessage() . PHP_EOL;
                return ['status' => 0, 'msg' => $e->getErrorMessage()];
            }
        }
    }

    /*
     * Raghu 19-7-8
     * 验证手机短信验证码
     * $phone :手机号码
     * $scene : 使用场景
     * $code : 验证码
     */
    public static function checkSmsCode($phone, $scene, $code)
    {

        $scene_arr = config('constant.sms_scene');

        $key = 'code:' . $phone . ':' . $scene_arr[$scene];
        if ($code == Redis::get($key)) {
            return true;
        } else {
            return false;
        }


    }

    /* 已废弃
     * Raghu 19-7-12
     * 视频上传
     * $file:视频UploadedFile对象
     * $path:oss服务器上传路径
     */
    public static function uploadsVideo($file, $path, $name = "视频")
    {
        $input = ['file' => $file];
        $rules = [
            'file' => 'mimetypes:video/avi,video/mpeg,video/quicktime,video/mp4'
        ];
        $message = [
            'file.mimetypes' => '请上传正确格式的视频'
        ];
        $validator = \Validator::make($input, $rules, $message);

        if (!$validator->passes()) {//通过表单验证
            $msg = array_values($validator->getMessageBag()->getMessages())[0];
            throw new AllValidatorException(['msg' => $msg]);
        }

        //上传视频
        $oss = Utilities::ossUploads($file, $path);
        //制作缩略图
        $img = $oss['ossName'] . "?x-oss-process=video/snapshot,t_1,f_jpg,m_fast";

        $new_video = new Video();

        $new_video->name = $name;
        $new_video->url = $oss['ossName'];
        $new_video->thumb = $img;
        $new_video->save();

        return $new_video;


    }

    /* 已废弃
     * Raghu 19-7-12
     * 图片上传
     */
    public static function uploadsImg($file, $path, $name = "图片")
    {
        $input = ['file' => $file];
        $rules = [
            'file' => 'file|image'
        ];
        $message = [
            'file.image' => '请上传正确格式的图片'
        ];
        $validator = \Validator::make($input, $rules, $message);

        if (!$validator->passes()) {//通过表单验证
            $msg = array_values($validator->getMessageBag()->getMessages())[0];
//            throw new ValidatorException(new MessageBag([$msg]));
            throw new AllValidatorException(['msg' => $msg, 'statusCode' => 400, 'errorCode' => 400]);
        }

        $oss = Utilities::ossUploads($file, $path);

        $new_picture = new Picture();
        $new_picture->name = $name;
        $new_picture->image = $oss['ossName'];
        $new_picture->save();

        return $new_picture;

    }

    /*
     * Raghu 19-7-12
     * 文件上传阿里Oss
     */
    public static function ossUploads($file, $oss_path)
    {

        $originalName = $file->getClientOriginalName(); // 文件原名
        $ext = $file->getClientOriginalExtension();     // 扩展名
        $realPath = $file->getRealPath();   //临时文件的绝对路径

        $accessKeyId = config('constant.aliOss.access_key_id');
        $accessKeySecret = config('constant.aliOss.access_key_secret');
        $endpoint = config('constant.aliOss.endpoint');
        $bucket = config('constant.aliOss.bucket');

        $file_name = md5($originalName . time()) . '.' . $ext;

        $object = $oss_path . "/" . $file_name;
        $filePath = $realPath;

        try {
            $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);

            $ossClient->uploadFile($bucket, $object, $filePath);

            $ossName = 'https://' . $bucket . '.oss-cn-qingdao.aliyuncs.com/' . $oss_path . '/' . $file_name;
            return ['status' => 1, 'ossName' => $ossName];
        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getCode() . "\n" . $e->getMessage() . "\n");
            return ['status' => 0, 'msg' => '上传失败'];
        }
    }

    /*
     * 处理分页数据 Raghu 19-7-15
     */
    public static function dealPage($list)
    {
        $list = is_array($list) ? $list : $list->toArray();
        $current_page = $list['current_page']; //当前页
        $last_page = $list['last_page'];       //最后页
        $total = $list['total'];               //总量
        $next_page = 0;                        //下一页
        $pre_page = 0;                        //上一页
        $is_last_page = 0;
        $data = $list['data'];

        if ($current_page != $last_page) {
            $next_page = $current_page + 1;
        } else {
            $next_page = null;
            $is_last_page = 1;
        }

        if ($current_page != 1) {
            $pre_page = $current_page - 1;
        } else {
            $pre_page = null;
        }


        $new_list = [
            'current_page' => $current_page,
            'last_page' => $last_page,
            'items' => $data,
            'total' => $total,
            'next_page' => $next_page,
            'pre_page' => $pre_page,
            'is_last_page' => $is_last_page,
        ];
        return $new_list;
    }

    /**
     * 根据用户角色数组返回 八位二进制字符串
     * @param $role array
     * @return string
     */
    public static function getRoleBool($role)
    {
        if (empty($role)) {
            $role_bool = '00000000';
        } else {
            $roleList = array_unique(array_column($role, 'rid'));
            $roleStatus = array_flip(config('constant.role'));
            $roleBool = config('constant.roleBool');
            $role_bool = array_map(function ($v) use ($roleStatus, $roleBool) {
                return $roleBool[$roleStatus[$v]];
            }, $roleList);
            $role_bool = array_reduce($role_bool, function ($v, $k) {
                return $v = $v | $k;
            }, '00000000');
        }
        return $role_bool;
    }

    /**
     * 获取图片地址
     * @param $imgId
     * @return string
     */
    public static function getImgUrl($imgId)
    {
        $res = (new Picture())->find($imgId);
        return empty($res) ? '' : $res->image;
    }

    /**
     * 时间戳转字符串
     * @param $date
     * @return false|string
     */
    public static function formatDate($date)
    {
        return date('Y-m-d H:i:s', $date);
    }

    /**
     * 数字转换为中文
     * @param integer $num 目标数字
     */
    public static function numberToChinese($num)
    {
        if (is_int($num) && $num < 100) {
            $char = array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九');
            $unit = ['', '十', '百', '千', '万'];
            $return = '';
            if ($num < 10) {
                $return = $char[$num];
            } elseif ($num % 10 == 0) {
                $firstNum = substr($num, 0, 1);
                if ($num != 10) $return .= $char[$firstNum];
                $return .= $unit[strlen($num) - 1];
            } elseif ($num < 20) {
                $return = $unit[substr($num, 0, -1)] . $char[substr($num, -1)];
            } else {
                $numData = str_split($num);
                $numLength = count($numData) - 1;
                foreach ($numData as $k => $v) {
                    if ($k == $numLength) continue;
                    $return .= $char[$v];
                    if ($v != 0) $return .= $unit[$numLength - $k];
                }
                $return .= $char[substr($num, -1)];
            }
            return $return;
        }
    }

    public static function to_entities($string)
    {
        $len = strlen($string);
        $buf = "";
        for ($i = 0; $i < $len; $i++) {
            if (ord($string[$i]) <= 127) {
                $buf .= $string[$i];
            } else if (ord($string[$i]) < 192) {
                //unexpected 2nd, 3rd or 4th byte
                $buf .= "?";
            } else if (ord($string[$i]) < 224) {
                //first byte of 2-byte seq
                $buf .= sprintf("&#%d;",
                    ((ord($string[$i + 0]) & 31) << 6) +
                    (ord($string[$i + 1]) & 63)
                );
                $i += 1;
            } else if (ord($string[$i]) < 240) {
                //first byte of 3-byte seq
                $buf .= sprintf("&#%d;",
                    ((ord($string[$i + 0]) & 15) << 12) +
                    ((ord($string[$i + 1]) & 63) << 6) +
                    (ord($string[$i + 2]) & 63)
                );
                $i += 2;
            } else {
                //first byte of 4-byte seq
                $buf .= sprintf("&#%d;",
                    ((ord($string[$i + 0]) & 7) << 18) +
                    ((ord($string[$i + 1]) & 63) << 12) +
                    ((ord($string[$i + 2]) & 63) << 6) +
                    (ord($string[$i + 3]) & 63)
                );
                $i += 3;
            }
        }
        return $buf;
    }

    public static function getStoreLevel($orderNums)
    {
        $levels = 1;
        if (empty($orderNums)) $orderNums = 1;
        if ($orderNums = 0 && $orderNums <= 1000) {
            switch ($orderNums) {
                case $orderNums = 0 && $orderNums <= 10:
                    $levels = 1;
                    break;
                case $orderNums > 10 && $orderNums <= 100:
                    $levels = 2;
                    break;
                case $orderNums > 100 && $orderNums <= 300:
                    $levels = 3;
                    break;
                case $orderNums > 300 && $orderNums <= 600:
                    $levels = 4;
                    break;
                case $orderNums > 600 && $orderNums <= 1000:
                    $levels = 5;
                    break;
            }
        } else if ($orderNums <= config('storeLevel.diamond.end')) {
            $diamond = config('storeLevel.diamond');
            for ($j = 0; $diamond['start'] <= $diamond['end']; $j++) {
                $start = $diamond['start'];
                $end = $diamond['start'] + $diamond['step'];
                if ($end >= $orderNums && $start < $orderNums) {
                    $levels = (5 + $j + 1);
                }
                $diamond['start'] = $end;
            }
        } else if ($orderNums <= config('storeLevel.crown.end')) {
            $crown = config('storeLevel.crown');
            for ($j = 0; $crown['start'] <= $crown['end']; $j++) {
                $start = $crown['start'];
                $end = $crown['start'] + $crown['step'];
                if ($end >= $orderNums && $start < $orderNums) {
                    $levels = (10 + $j + 1);
                }
                $crown['start'] = $end;
            }
        }

        return [
            'type' => (intval($levels / 5) + 1),
            'num' => intval($levels % 5) == 0 ? 5 : intval($levels % 5)
        ];

    }

    public static function urlSafeBase64Encode($url)
    {
        $url = base64_encode($url);
        $url = str_replace(array('+','/','='),array('-','_',''),$url);
        return $url;
    }
}